import React, { MouseEvent, useEffect, useState } from 'react'
import "./calendar.scss"

interface Props {
    title?: React.ReactNode,
    defaultValue?: Date,
    change?: (date: Date) => void,
    cellRender?: (current: Date) => React.ReactNode
}

const Calendar = ({ title, defaultValue = new Date(), change = () => { }, cellRender = () => null }: Props) => {
    // 显示的年月
    const [showYear, setShowYear] = useState<number>(0)
    const [showMonth, setShowMonth] = useState<number>(0)

    // 最终选择的年月日
    const [activeYear, setActiveYear] = useState<number>(0)
    const [activeMonth, setActiveMonth] = useState<number>(0)
    const [activeDay, setActiveDay] = useState<number>(0)

    // 去年
    const preYear = (e: MouseEvent<HTMLElement>) => {
        e.stopPropagation()
        setShowYear(showYear - 1)
    }

    // 上月
    const preMonth = (e: MouseEvent<HTMLElement>) => {
        e.stopPropagation()
        if (showMonth - 1 >= 1) {
            setShowMonth(showMonth - 1)
        } else {
            setShowYear(showYear - 1)
            setShowMonth(12)
        }
    }

    // 明年
    const nextYear = (e: MouseEvent<HTMLElement>) => {
        e.stopPropagation()
        setShowYear(showYear + 1)
    }

    // 下个月
    const nextMonth = (e: MouseEvent<HTMLElement>) => {
        e.stopPropagation()
        if (showMonth + 1 <= 12) {
            setShowMonth(showMonth + 1)
        } else {
            setShowYear(showYear + 1)
            setShowMonth(1)
        }
    }

    // 日列表
    interface DayInterface {
        index: number,
        value: number,
        active: boolean,
        thisMonth: 'this' | 'pre' | 'next',
        node?: React.ReactNode
    }

    const [dayList, setDayList] = useState<Array<Array<DayInterface>>>([
        [
            {
                index: 1,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 2,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 3,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 4,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 5,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 6,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 7,
                value: 1,
                active: false,
                thisMonth: 'this'
            }
        ], [
            {
                index: 8,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 9,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 10,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 11,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 12,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 13,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 14,
                value: 1,
                active: false,
                thisMonth: 'this'
            }
        ], [
            {
                index: 15,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 16,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 17,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 18,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 19,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 20,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 21,
                value: 1,
                active: false,
                thisMonth: 'this'
            }
        ], [
            {
                index: 22,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 23,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 24,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 25,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 26,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 27,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 28,
                value: 1,
                active: false,
                thisMonth: 'this'
            }
        ], [
            {
                index: 29,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 30,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 31,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 32,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 33,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 34,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 35,
                value: 1,
                active: false,
                thisMonth: 'this'
            }
        ], [
            {
                index: 36,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 37,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 38,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 39,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 40,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 41,
                value: 1,
                active: false,
                thisMonth: 'this'
            }, {
                index: 42,
                value: 1,
                active: false,
                thisMonth: 'this'
            }
        ],
    ])

    useEffect(() => {
        setActiveYear(defaultValue.getFullYear())
        setActiveMonth(defaultValue.getMonth() + 1)
        setActiveDay(defaultValue.getDate())
        setShowYear(defaultValue.getFullYear())
        setShowMonth(defaultValue.getMonth() + 1)
    }, [])

    // 获取月份最后一天
    const getLastDay = (year: number, month: number): number => {
        if (month <= 0) {
            year -= 1
            month = 12
        } else if (month >= 13) {
            year += 1
            month = 1
        }
        const isLeapYear = ((year % 4) == 0) && ((year % 100) != 0) || ((year % 400) == 0)
        const maxDays = [1, 3, 5, 7, 8, 10, 12]
        const middleDays = [4, 6, 9, 11]
        if (month == 2) {
            if (isLeapYear) {
                return 29
            } else {
                return 28
            }
        } else if (maxDays.includes(month)) {
            return 31
        } else if (middleDays.includes(month)) {
            return 30
        }
        return 30
    }

    // 点击日期
    const onClick = (index: number) => {
        const dayList1: Array<Array<DayInterface>> = JSON.parse(JSON.stringify(dayList))
        dayList1.forEach(days => {
            days.forEach(day => {
                if (day.index === index) {
                    let showMonth1: number = showMonth
                    let showYear1: number = showYear
                    if (day.thisMonth === 'this') {
                        day.active = true
                    } else if (day.thisMonth === 'pre') {
                        // 选择上个月
                        showMonth1--
                        if (showMonth1 <= 0) {
                            showYear1--
                            showMonth1 = 12
                        }
                    } else {
                        // 选择下个月
                        showMonth1++
                        if (showMonth1 > 12) {
                            showYear1++
                            showMonth1 = 1
                        }
                    }
                    setShowYear(showYear1)
                    setShowMonth(showMonth1)
                    setActiveYear(showYear1)
                    setActiveMonth(showMonth1)
                    setActiveDay(day.value)
                    change(new Date(`${showYear1}-${showMonth1}-${day.value}`))
                } else {
                    day.active = false
                }
            })
        })
        setDayList(dayList1)
    }

    useEffect(() => {
        const newYear: number = showYear
        const newMonth: number = showMonth
        // 获取月第一天和最后一天
        const lastDay = getLastDay(newYear, newMonth)
        const firstDate = new Date(`${newYear}-${newMonth}-1`)
        let preMonth = newMonth - 1
        let preYear = newYear
        if (preMonth <= 0) {
            preYear--
            preMonth = 12
        }
        const prelastDay = getLastDay(preYear, preMonth)
        const firstDay = firstDate.getDay() === 0 ? 7 : firstDate.getDay()
        let count = 2 - firstDay
        const dayList1: Array<Array<DayInterface>> = JSON.parse(JSON.stringify(dayList))
        dayList1.forEach(days => {
            days = days.map(day => {
                if (count <= 0) {
                    // 上个月的日期
                    day.thisMonth = 'pre'
                    day.value = count + prelastDay
                } else if (count > lastDay) {
                    // 下个月的日期
                    day.thisMonth = 'next'
                    day.value = count - lastDay
                } else {
                    // 这个月的日期
                    day.thisMonth = 'this'
                    day.value = count
                }
                count++
                if (newYear === activeYear && newMonth === activeMonth && day.value === activeDay && day.thisMonth === 'this') {
                    day.active = true
                } else {
                    day.active = false
                }
                return day
            })
        })
        setDayList(dayList1)
    }, [showYear, showMonth])

    const cellRender1 = (day: DayInterface) => {
        let year: number = showYear
        let month: number = showMonth
        if (day.thisMonth === 'pre' || day.thisMonth === 'next') {
            return null
        }
        return cellRender(new Date(`${year}-${month}-${day.value}`))
    }

    return (
        <div className="pe-calendar">
            {
                title === 0 || title ? (
                    <div className="pe-calendar-title">
                        {title}
                    </div>
                ) : null
            }
            <div className="pe-calendar-content">
                <div className="pe-calendar-header">
                    <i className="pe-icon" onClick={preYear}>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                            <path fill="currentColor"
                                d="M529.408 149.376a29.12 29.12 0 0 1 41.728 0 30.592 30.592 0 0 1 0 42.688L259.264 511.936l311.872 319.936a30.592 30.592 0 0 1-.512 43.264 29.12 29.12 0 0 1-41.216-.512L197.76 534.272a32 32 0 0 1 0-44.672l331.648-340.224zm256 0a29.12 29.12 0 0 1 41.728 0 30.592 30.592 0 0 1 0 42.688L515.264 511.936l311.872 319.936a30.592 30.592 0 0 1-.512 43.264 29.12 29.12 0 0 1-41.216-.512L453.76 534.272a32 32 0 0 1 0-44.672l331.648-340.224z">
                            </path>
                        </svg>
                    </i>
                    <i className="pe-icon" onClick={preMonth}>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                            <path fill="currentColor"
                                d="M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z">
                            </path>
                        </svg>
                    </i>
                    <span className="pe-calendar-text">{showYear}年&nbsp;{showMonth}月</span>
                    <i className="pe-icon" onClick={nextMonth}>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                            <path fill="currentColor"
                                d="M340.864 149.312a30.592 30.592 0 0 0 0 42.752L652.736 512 340.864 831.872a30.592 30.592 0 0 0 0 42.752 29.12 29.12 0 0 0 41.728 0L714.24 534.336a32 32 0 0 0 0-44.672L382.592 149.376a29.12 29.12 0 0 0-41.728 0z">
                            </path>
                        </svg>
                    </i>
                    <i className="pe-icon" onClick={nextYear}>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                            <path fill="currentColor"
                                d="M452.864 149.312a29.12 29.12 0 0 1 41.728.064L826.24 489.664a32 32 0 0 1 0 44.672L494.592 874.624a29.12 29.12 0 0 1-41.728 0 30.592 30.592 0 0 1 0-42.752L764.736 512 452.864 192a30.592 30.592 0 0 1 0-42.688m-256 0a29.12 29.12 0 0 1 41.728.064L570.24 489.664a32 32 0 0 1 0 44.672L238.592 874.624a29.12 29.12 0 0 1-41.728 0 30.592 30.592 0 0 1 0-42.752L508.736 512 196.864 192a30.592 30.592 0 0 1 0-42.688z">
                            </path>
                        </svg>
                    </i>
                </div>
                <table className="pe-calendar-table">
                    <thead className="pe-calendar-thead">
                        <tr>
                            <td>一</td>
                            <td>二</td>
                            <td>三</td>
                            <td>四</td>
                            <td>五</td>
                            <td>六</td>
                            <td>日</td>
                        </tr>
                    </thead>
                    <tbody className="pe-calendar-tbody">
                        {
                            dayList.map((days, index) => (
                                <tr key={index}>
                                    {
                                        days.map(day => (
                                            <td key={day.index}
                                                className={[day.active ? 'pe-calendar-active' : '', day.thisMonth === 'this' ? '' : 'pe-calendar-not'].join(" ").trim()}
                                                onClick={(e) => {
                                                    e.stopPropagation()
                                                    onClick(day.index)
                                                }}>
                                                <div className="pe-calendar-item">
                                                    <div className='pe-calendar-item-value'>{day.value.toString()}</div>
                                                    {
                                                        cellRender1(day) || cellRender1(day) === 0 ? <div className='pe-calendar-item-slot'>{cellRender1(day)}</div> : null
                                                    }
                                                </div>
                                            </td>
                                        ))
                                    }
                                </tr>
                            ))
                        }
                    </tbody>
                </table>
            </div>
        </div>
    )
}

export default Calendar
